package com.zyk.scaffold.oauth.framework;

import com.zyk.scaffold.oauth.framework.config.properties.OauthProperties;
import com.zyk.scaffold.oauth.framework.defaults.DefaultTokenGranter;
import com.zyk.scaffold.oauth.framework.defaults.DefaultTokenService;
import com.zyk.scaffold.oauth.framework.domain.*;
import com.zyk.scaffold.oauth.framework.exception.OauthException;
import com.zyk.scaffold.oauth.framework.exception.OauthExceptionEnum;
import com.zyk.scaffold.oauth.framework.interfaces.*;
import com.zyk.scaffold.common.utils.StringUtils;


public class OauthManager {
    private ITokenGranter tokenGranter;
    private ITokenService tokenService;
    private IClientDetailsService clientDetailsService;
    private ILoginCallBcak loginCallBcak;
    private IUserDetailsService userDetailsService;
    private OauthProperties oauthProperties;
    public OauthManager() {
        this.oauthProperties = new OauthProperties();
    }

    public OauthManager(OauthProperties oauthProperties) {
        this.oauthProperties = oauthProperties;
    }

    public AccessToken login(OauthRequest request) throws OauthException {
        OauthContext context = getTokenGranter().grant(request);
        if(null == context){
            throw new OauthException(OauthExceptionEnum.Default);
        }
        AccessToken accessToken = getTokenService().createdToken(context);
        if(loginCallBcak != null){
            try {
                loginCallBcak.success(accessToken);
            }catch (Exception ex){
                // ex
            }
        }
        return accessToken;
    }

    public AccessToken getAccessToken(String token) throws OauthException {
        return getTokenService().getAccessToken(token);
    }

    public RefreshToken getRefreshToken(String refreshToken)  throws OauthException{
        return getTokenService().getRefreshToken(refreshToken);
    }

    public Boolean logout(String accessToken)  throws OauthException{
        if(StringUtils.isEmpty(accessToken)){
            throw new OauthException(OauthExceptionEnum.AccessTokenIsNotEmpty);
        }
        return getTokenService().removeToken(accessToken);
    }

    public boolean registerGrant(ITokenGranter tokenGranter) throws OauthException {
        return getTokenGranter().registerGrant(tokenGranter);
    }

    public String createdAuthorizationCode(Long userId, String clientId, String domain)  throws OauthException{
        ClientDetails clientDetails = getClientDetailsService().loadClientDetailsByClientId(clientId);
//        if(clientDetails.getDomains().indexOf(domain) < 0){
//            throw new OauthException(OauthExceptionEnum.DomainIsNotExist);
//        }
        AuthorizationCodeDetails authorizationCodeDetails = new AuthorizationCodeDetails(userId, clientId);
        String authorizationCode = getTokenService().createdAuthorizationCode(authorizationCodeDetails);
        if(null == authorizationCode){
            throw new OauthException(OauthExceptionEnum.AuthorizationCodeCreateFiled);
        }
        return authorizationCode;
    }

    public AuthorizationCodeDetails validateAuthorizationCode(String clientId, String ip , String authorizationCode) throws OauthException {
//        ClientDetails clientDetails = getClientDetailsService().loadClientDetailsByClientId(clientId);
//        if(clientDetails.getIps().indexOf(ip) < 0){
//            throw new OauthException(OauthExceptionEnum.IpIsNotExist);
//        }
        return getTokenService().validateAuthorizationCode(authorizationCode);
    }

    public ITokenGranter getTokenGranter() {
        if(tokenGranter == null){
            tokenGranter = new DefaultTokenGranter(this);
        }
        return tokenGranter;
    }

    public void setTokenGranter(ITokenGranter tokenGranter) {
        this.tokenGranter = tokenGranter;
    }

    public ITokenService getTokenService() {
        if(tokenService == null){
            tokenService = new DefaultTokenService(oauthProperties);
        }
        return tokenService;
    }

    public void setTokenService(ITokenService tokenService) {
        this.tokenService = tokenService;
    }

    public IClientDetailsService getClientDetailsService() {
        if(clientDetailsService == null){
            throw new OauthException(OauthExceptionEnum.ClientDetailsServiceIsNotExist);
        }
        return clientDetailsService;
    }

    public void setClientDetailsService(IClientDetailsService clientDetailsService) {
        this.clientDetailsService = clientDetailsService;
    }

    public void setLoginCallBcak(ILoginCallBcak loginCallBcak) {
        this.loginCallBcak = loginCallBcak;
    }

    public IUserDetailsService getUserDetailsService() {
        if(userDetailsService == null){
            throw new OauthException(OauthExceptionEnum.UserDetailsServiceIsNotExist);
        }
        return userDetailsService;
    }

    public void setUserDetailsService(IUserDetailsService userDetailsService) {
        this.userDetailsService = userDetailsService;
    }
}
